# 公司：安徽银杰
# 作者：李伟

"""
函数封装步骤：
1、功能代码写出来
2、def封装
3、参数化： 变化的数据定义为形参
4、返回值： 判断函数是否有数据需要给调用的人使用
   - 最终就是为了得到这个替换完成之后的字符串

封装的函数的优化：
1、记录日志： 方便问题定位 看到执行过程 == 但凡print看结果 或者debug看结果的地方都记录日志
2、因为有些用例可能没有在用例没有头部 参数 读取为空
 - 如果没有提取表达式 读出来的就是None  不能做反序列化。

优化的问题：--优化replace函数
1、目前函数值识别了变量名 去环境变量替换数据
2、并没有处理占位符里是函数名情况
  -如果是函数名的话 需要调用函数 执行函数  得到函数执行返回值的。
3、分支判断：
  - 如果mark是函数名字，以括号结尾或者() in mark：  "#gen_unregister_phone()#"
  - 如果mark是变量名：

"""
import allure
from data.envi_data import EnviData
from loguru import logger
import re
@allure.step("数据占位符替换")
def replace_mark(str_data):  #str_data 作为excel中的请求参数。
    if str_data is None:  #判断请求参数是否为空，有些接口无需请求参数。
        logger.info("数据为空，不需要做替换操作，直接返回！")
        return
    result = re.findall("#(.*?)#",str_data)  #正则表达式findall(正式表达式，目标字符串)。
    # 1、先判断一下这个正则查找的结果列表是否为空
    if result: # 如果列表非空
        logger.info("-------------------开始替换数据-----------------------")
        logger.info(f"要替换的原始数据是：{str_data}")
        logger.info(f"要替换的占位符有：{result}")
        # 2、for循环遍历这个列表里的变量名
        for mark in result:
            # 分支判断：如果mark是函数名字，以括号结尾或者()
            if "()" in mark:  # mark 是gen_unregister_phone()
                # mark是字符串类型 是函数 调用执行函数
                # 要在这个模块里执行函数 导包
                gen_data = eval(f'GenData().{mark}')  # eval('GenData().gen_unregister_phone()')
                # 得到了随机生成数据 存在环境变量里：属性名-函数名去掉括号， 属性值 -- 函数结果
                var_name = mark.strip("()")  # 属性名-函数名去掉括号
                setattr(EnviData, var_name, gen_data)
                # 替换掉字符串里本身的占位符--用函数结果替换 {"mobile":"#gen_unregister_phone()#"}
                str_data = str_data.replace(f"#{mark}#", str(gen_data))
                logger.info(f"环境变量的数据为：{EnviData.__dict__}")
            else:
            # 3、判断这个变量名是否存在环境变量的属性名 【类里是否有这个属性】
                if hasattr(EnviData,mark):
                    # 4、如果有这个属性 替换属性值
                    str_data = str_data.replace(f"#{mark}#",str(getattr(EnviData,mark))) # 转化为字符串类型
                    #如果存在变量名，就获取变量值，然后替换#{Mar}k#  变量值。
    else:
        logger.info(f"要替换的占位符为空：{result}，不需要做替换")
    logger.info(f"替换完成之后的字符串为：{str_data}")
    return str_data

if __name__ == '__main__':
    class EnviData:
        prodId = 123
        skuId = 456
    str_data = '{"basketId": 0, "count": 1111, "prodId": #prodId#, "shopId": 1, "skuId": #skuId#}'
    print(replace_mark(str_data))

# 总结：
# 主要作用：

# 正则查找excel中 某些特定的字符，然后提取变量名到 环境类属性中查找是否存在这个类属性名，如存在即可执行替换。全局变量

# 1、Excel请求参数列进行处理。先判空，如果参数数据为空，则就不需要替换。
# 2、正则匹配结果，匹配目标字符串中的 占位符。##
# 3、判断占位符是否为空，为空直接打印为空数据。
# 4、不为None的情况下，需要判断占位符的格式，一般是正常字符串占位符，特殊情况下占位符是函数。
#      a、正常占位符，直接 hasattr(EnviData,mark) 查找环境变量中是否存在属性名。
#             存在的话直接替换str_data = str_data.replace(f"#{mark}#",str(getattr(EnviData,mark))),打印属性。
#             如果有变量属性的话需要获取替换getattr(EnviData,mark))
#      b、函数占位符，判断 占位符中是否包含（） 如果有则表明占位符是一个函数。那么就需要执行函数，得到执行后的数据。
#         这里需要注意，需要知道占位符是什么样的随机数据，才能导入函数。
#           gen_data = eval(f'GenData().{mark}') #因为mark是字符串所以需要脱引号处理。
#           # 拿到占位符的变量名。
#           var_name = mark.strip("()") # 属性名-函数名去掉括号
#           # 设置环境变量
#           setattr(EnviData,var_name,gen_data)
#           然后直接替换占位符 str_data = str_data.replace(f"#{mark}#",str(gen_data))

            # 注意：这里的函数是正则匹配参数中的占位符，执行数据后，直接运行函数，设置环境变量，在替换的。如果正常存在变量属性，则不需要重新setattr